home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / showlfssegment / RCS / showlfssegment.c,v < prev   
Encoding:
Text File  |  1992-03-12  |  16.6 KB  |  600 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    shirriff:1.1; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     92.03.11.21.54.25;  author shirriff;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @@
  17.  
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/* 
  26.  * showlfssegment.c --
  27.  *
  28.  *    The showlfssegment program - Show the segment usage of an
  29.  *    LFS file system.
  30.  *
  31.  * Copyright 1989 Regents of the University of California
  32.  * Permission to use, copy, modify, and distribute this
  33.  * software and its documentation for any purpose and without
  34.  * fee is hereby granted, provided that the above copyright
  35.  * notice appear in all copies.  The University of California
  36.  * makes no representations about the suitability of this
  37.  * software for any purpose.  It is provided "as is" without
  38.  * express or implied warranty.
  39.  */
  40.  
  41. #ifndef lint
  42. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.2 89/01/07 04:12:18 rab Exp $ SPRITE (Berkeley)";
  43. #endif /* not lint */
  44.  
  45. #include "lfslib.h"
  46. #ifdef _HAS_PROTOTYPES
  47. #include <varargs.h>
  48. #endif
  49.  
  50. #include <sprite.h>
  51. #include <stdio.h>
  52. #include <option.h>
  53. #include <sys/types.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include <sys/file.h>
  57.  
  58.  
  59. int    blockSize = 512;
  60. int    offset = 64;
  61.  
  62. char    *deviceName;
  63.  
  64. Option optionArray[] = {
  65.     {OPT_DOC, (char *) NULL,  (char *) NULL,
  66.     "This program shows the usage of an LFS file system.\n Synopsis: \"showLfsUsage [switches] deviceName\"\n Command-line switches are:"},
  67.     {OPT_INT, "blockSize", (Address) &blockSize, 
  68.     "Block size of file system."},
  69.     {OPT_INT, "offset", (Address) &offset, 
  70.     "Offset into device to start file system."},
  71. };
  72. /*
  73.  * Forward routine declartions. 
  74.  */
  75.  
  76. static void PrintSegUsageSummary _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr,
  77.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  78. static void PrintDescMapSummary _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr, 
  79.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  80. static void PrintFileLayoutSummary _ARGS_((Lfs *lfsPtr, LfsSeg *segPtr,
  81.     int startAddr, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  82. static void ShowDirLogBlock _ARGS_((LfsDirOpLogBlockHdr *hdrPtr, int addr));
  83.  
  84. static char *DirOpFlagsToString _ARGS_((int opFlags));
  85. static char *FileTypeToString _ARGS_((int fileType));
  86.  
  87. static void PrintSegmentContents _ARGS_((Lfs *lfsPtr, int segNum));
  88. extern void panic();
  89.  
  90.  
  91. /*
  92.  *----------------------------------------------------------------------
  93.  *
  94.  * main --
  95.  *
  96.  *    Main routine of mklfs - parse arguments and do the work.
  97.  *
  98.  * Results:
  99.  *    None.
  100.  *
  101.  * Side effects:
  102.  *    None.
  103.  *
  104.  *----------------------------------------------------------------------
  105.  */
  106.  
  107. int
  108. main(argc,argv)
  109.     int    argc;
  110.     char *argv[];
  111. {
  112.     Lfs    *lfsPtr;
  113.     int    segNum;
  114.  
  115.  
  116.  
  117.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  118.     if (argc != 3) { 
  119.          Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  120.      exit(1);
  121.      segNum = 0; /* Lint avoidance. */
  122.     } else {
  123.     deviceName = argv[1];
  124.     segNum = atoi(argv[2]);
  125.     }
  126.     lfsPtr = LfsLoadFileSystem(argv[0], deviceName, blockSize, offset,
  127.                  O_RDONLY);
  128.     if (lfsPtr == (Lfs *) NULL) {
  129.     exit(1);
  130.     }
  131.     if ((segNum < 0 || segNum >= lfsPtr->superBlock.usageArray.numberSegments) &&
  132.     (segNum != -1) ) {
  133.     fprintf(stderr, "%s: Bad segment number %s\n", argv[0], argv[2]);
  134.     exit(1);
  135.     }
  136.     if (segNum == 0) {
  137.     for (segNum = 1; segNum < lfsPtr->superBlock.usageArray.numberSegments;
  138.         segNum++) { 
  139.  
  140.  
  141.         printf("Segment number %d\n", segNum);
  142.         PrintSegmentContents(lfsPtr, segNum);
  143.     }
  144.     } else {
  145.  
  146.  
  147.     printf("Segment number %d\n", segNum);
  148.     PrintSegmentContents(lfsPtr, segNum);
  149.     }
  150.  
  151.     exit(0);
  152.     return 0;
  153. }
  154.  
  155.  
  156. /*
  157.  *----------------------------------------------------------------------
  158.  *
  159.  * PrintSegmentContents --
  160.  *
  161.  *    Print out the contents of an LFS segement.
  162.  *
  163.  * Results:
  164.  *    None.
  165.  *
  166.  * Side effects:
  167.  *    None.
  168.  *
  169.  *----------------------------------------------------------------------
  170.  */
  171. static void
  172. PrintSegmentContents(lfsPtr, segNum)
  173.     Lfs    *lfsPtr;    /* File system. */
  174.     int    segNum;        /* LfsSegment number. */
  175. {
  176.     LfsSeg    *segPtr;
  177.     int startAddr;
  178.     char *summaryLimitPtr, *summaryPtr;
  179.     LfsSegSummary *segSummaryPtr;
  180.     LfsSegSummaryHdr *segSummaryHdrPtr;
  181.     int blockOffset;
  182.  
  183.  
  184.     blockOffset = 0;
  185.     segPtr = LfsSegInit(lfsPtr, segNum);
  186.     startAddr = LfsSegStartAddr(segPtr) + LfsSegSizeInBlocks(lfsPtr);
  187.     do { 
  188.     segSummaryPtr = (LfsSegSummary *) 
  189.             LfsSegFetchBlock(segPtr, blockOffset, blockSize);
  190.     if (segSummaryPtr->size == 0) {
  191.         LfsSegReleaseBlock(segPtr, (char *) segSummaryPtr);
  192.         break;
  193.     }
  194.     if (segSummaryPtr->magic != LFS_SEG_SUMMARY_MAGIC) {
  195.         fprintf(stderr,"%s: Bad magic number 0x%x for summary region of segment %d\n", deviceName, segSummaryPtr->magic, segNum);
  196.         break;
  197.     }
  198.     printf("Addr %d Summary Time %d PrevSeg %d NextSeg %d bytes %d NextSum %d\n",
  199.         startAddr-blockOffset,
  200.         segSummaryPtr->timestamp, segSummaryPtr->prevSeg, 
  201.         segSummaryPtr->nextSeg,
  202.         segSummaryPtr->size, segSummaryPtr->nextSummaryBlock);
  203.     blockOffset++;
  204.     summaryLimitPtr = (char *) segSummaryPtr + segSummaryPtr->size;
  205.     summaryPtr = (char *) (segSummaryPtr + 1);
  206.     while (summaryPtr < summaryLimitPtr) {
  207.        segSummaryHdrPtr = (LfsSegSummaryHdr *) summaryPtr;
  208.        if (segSummaryHdrPtr->lengthInBytes == 0) {
  209.         break;
  210.        }
  211.        switch (segSummaryHdrPtr->moduleType) { 
  212.        case LFS_SEG_USAGE_MOD:
  213.           PrintSegUsageSummary(lfsPtr, segPtr, startAddr - blockOffset, blockOffset, 
  214.                 segSummaryHdrPtr);
  215.            break;
  216.        case LFS_DESC_MAP_MOD:
  217.           PrintDescMapSummary(lfsPtr, segPtr, startAddr - blockOffset, blockOffset, 
  218.                 segSummaryHdrPtr);
  219.            break;
  220.        case LFS_FILE_LAYOUT_MOD:
  221.           PrintFileLayoutSummary(lfsPtr, segPtr,startAddr - blockOffset, blockOffset, 
  222.                 segSummaryHdrPtr);
  223.         break;
  224.        default: {
  225.         fprintf(stderr,"%s:CheckSummary: Unknown module type %d at %d, Size %d Blocks %d\n",
  226.             deviceName, segSummaryHdrPtr->moduleType, startAddr - blockOffset, segSummaryHdrPtr->lengthInBytes, segSummaryHdrPtr->numDataBlocks);
  227.         break;
  228.         }
  229.        }
  230.        summaryPtr += segSummaryHdrPtr->lengthInBytes;
  231.        blockOffset += (segSummaryHdrPtr->numDataBlocks-1);
  232.        }
  233.        if (segSummaryPtr->nextSummaryBlock == -1) { 
  234.        blockOffset = 0;
  235.        } else {
  236.        blockOffset = segSummaryPtr->nextSummaryBlock-1;
  237.        }
  238.        LfsSegReleaseBlock(segPtr, (char *) segSummaryPtr);
  239.     } while( blockOffset != 0);
  240.     LfsSegRelease(segPtr);
  241. }
  242.  
  243. /*
  244.  *----------------------------------------------------------------------
  245.  *
  246.  * PrintSegUsageSummary --
  247.  *
  248.  *    Check the segment summary regions for the seg usage map.
  249.  *
  250.  * Results:
  251.  *    None.
  252.  *
  253.  * Side effects:
  254.  *    None.
  255.  *
  256.  *----------------------------------------------------------------------
  257.  */
  258. static void
  259. PrintSegUsageSummary(lfsPtr, segPtr, startAddress, offset, segSummaryHdrPtr) 
  260.     Lfs    *lfsPtr;
  261.     LfsSeg *segPtr;
  262.     int startAddress;
  263.     int offset;
  264.     LfsSegSummaryHdr *segSummaryHdrPtr;
  265. {
  266.     int blocks, *blockArray, i, startAddr, fsBlocks;
  267.  
  268.     fsBlocks = lfsPtr->superBlock.usageArray.stableMem.blockSize/blockSize;
  269.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  270.                 sizeof(int);
  271.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  272.     fprintf(stderr,"%s:PrintSegUsageSummary: Wrong block count; is %d should be %s\n", deviceName, blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  273.     }
  274.     blockArray = (int *) (segSummaryHdrPtr + 1);
  275.     for (i = 0; i < blocks; i++) {
  276.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  277.     if ((blockArray[i] < 0) || 
  278.         (blockArray[i] > lfsPtr->superBlock.usageArray.stableMem.maxNumBlocks)){
  279.        fprintf(stderr,"%s:PrintSegUsageSummary: Bad block number %d at %d\n",
  280.             deviceName,blockArray[i], startAddr);
  281.         continue;
  282.     }
  283.     printf("Addr %d UsageArray Block %d %s\n", startAddr, blockArray[i],
  284.         (LfsGetUsageArrayBlockIndex(lfsPtr,blockArray[i]) == 
  285.             startAddr) ? "alive" : "dead");
  286.     }
  287.  
  288. }
  289.  
  290. /*
  291.  *----------------------------------------------------------------------
  292.  *
  293.  * PrintDescMapSummary --
  294.  *
  295.  *    Check the segment summary regions for the desc map.
  296.  *
  297.  * Results:
  298.  *    None.
  299.  *
  300.  * Side effects:
  301.  *    None.
  302.  *
  303.  *----------------------------------------------------------------------
  304.  */
  305. static void
  306. PrintDescMapSummary(lfsPtr, segPtr, startAddress, offset, segSummaryHdrPtr) 
  307.     Lfs    *lfsPtr;
  308.     LfsSeg *segPtr;
  309.     int startAddress;
  310.     int offset;
  311.     LfsSegSummaryHdr *segSummaryHdrPtr;
  312. {
  313.     int blocks, *blockArray, i, startAddr, fsBlocks;
  314.  
  315.     fsBlocks = lfsPtr->superBlock.descMap.stableMem.blockSize/blockSize;
  316.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  317.                 sizeof(int);
  318.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  319.     fprintf(stderr,"%s:PrintDescMapSummary: Wrong block count; is %d should be %s\n", deviceName,blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  320.     }
  321.     blockArray = (int *) (segSummaryHdrPtr + 1);
  322.     for (i = 0; i < blocks; i++) {
  323.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  324.     if ((blockArray[i] < 0) || 
  325.         (blockArray[i] > lfsPtr->superBlock.descMap.stableMem.maxNumBlocks)){
  326.        fprintf(stderr,"%s:PrintDescMapSummary: Bad block number %d at %d\n",
  327.             deviceName,blockArray[i], startAddr);
  328.         continue;
  329.     }
  330.     printf("Addr %d DescMap Block %d %s\n", startAddr, blockArray[i],
  331.         (LfsGetDescMapBlockIndex(lfsPtr,blockArray[i]) == 
  332.             startAddr) ? "alive" : "dead");
  333.     }
  334.  
  335. }
  336.  
  337. /*
  338.  *----------------------------------------------------------------------
  339.  *
  340.  * PrintFileLayoutSummary --
  341.  *
  342.  *    Check the segment summary regions for the file layout code.
  343.  *
  344.  * Results:
  345.  *    None.
  346.  *
  347.  * Side effects:
  348.  *    None.
  349.  *
  350.  *----------------------------------------------------------------------
  351.  */
  352. static void
  353. PrintFileLayoutSummary(lfsPtr, segPtr, startAddr, offset, segSummaryHdrPtr) 
  354.     Lfs    *lfsPtr;
  355.     LfsSeg  *segPtr;
  356.     int startAddr;
  357.     int offset;
  358.     LfsSegSummaryHdr *segSummaryHdrPtr;
  359. {
  360.     char *summaryPtr, *limitPtr;
  361.     int descMapBlocks;
  362.     int startAddress,  ssize;
  363.     LfsDescMapEntry *entryPtr;
  364.     LfsFile    *filePtr;
  365.     ReturnStatus status;
  366.     Boolean dead;
  367.     int sizeJunk;
  368.  
  369.     ssize = LfsSegSize(lfsPtr);
  370.  
  371.  
  372.     startAddress = startAddr;
  373.     descMapBlocks = lfsPtr->superBlock.descMap.stableMem.blockSize/blockSize;
  374.     summaryPtr = (char *) (segSummaryHdrPtr + 1);
  375.     limitPtr = summaryPtr + segSummaryHdrPtr->lengthInBytes - 
  376.             sizeof(LfsSegSummaryHdr);
  377.     while (summaryPtr < limitPtr) {
  378.     switch (*(unsigned short *) summaryPtr) {
  379.     case LFS_FILE_LAYOUT_DESC: {
  380.         int        fileNumber;
  381.         int        slot;
  382.         LfsFileDescriptor    *descPtr;
  383.         descPtr = (LfsFileDescriptor *) LfsSegFetchBlock(segPtr, offset, 
  384.                         descMapBlocks*blockSize);
  385.         offset += descMapBlocks;
  386.         startAddress -= descMapBlocks;
  387.         for (slot = 0; slot < lfsPtr->superBlock.fileLayout.descPerBlock; 
  388.         slot++) {
  389.         int addr;
  390.         /*
  391.          * The descriptor block is terminated by an unallocated
  392.          * descriptor.
  393.          */
  394.         if (!(descPtr[slot].common.flags & FSDM_FD_ALLOC)) {
  395.             break;
  396.         }
  397.  
  398.         addr = startAddress + (slot * sizeof(LfsFileDescriptor))/
  399.                         blockSize;
  400.         fileNumber = descPtr[slot].fileNumber;
  401.         if ((fileNumber < 0) || 
  402.             (fileNumber >= lfsPtr->superBlock.descMap.maxDesc)) {
  403.            fprintf(stderr,"%s:PrintFileLayoutSummary: bad file number %d in desc block at %d\n", deviceName, fileNumber, startAddress);
  404.            continue;
  405.         }
  406.         entryPtr = LfsGetDescMapEntry(lfsPtr, fileNumber);
  407.         printf("Addr %d Descriptor %s %d len %d %s\n",
  408.             startAddress,
  409.             FileTypeToString(descPtr[slot].common.fileType),
  410.             descPtr[slot].fileNumber,
  411.             descPtr[slot].common.lastByte+1,
  412.             ((entryPtr == (LfsDescMapEntry*) NIL) ||
  413.              (entryPtr->blockAddress != startAddress)) ? "dead" :
  414.              "alive");
  415.          }
  416.         /*
  417.          * Skip over the summary bytes describing this block. 
  418.          */
  419.         summaryPtr += sizeof(LfsFileLayoutDesc);
  420.         LfsSegReleaseBlock(segPtr, (char *) descPtr);
  421.         break;
  422.     }
  423.     case LFS_FILE_LAYOUT_DATA: {
  424.         int    *blockArray;
  425.         int              i;
  426.         LfsFileLayoutSummary *fileSumPtr;
  427.         int firstBlock;
  428.         /*
  429.          * We ran into a data block. If it is still alive bring it into
  430.          * the cache. 
  431.          */
  432.          fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  433.         if ((fileSumPtr->fileNumber < 0) || 
  434.         (fileSumPtr->fileNumber >= lfsPtr->superBlock.descMap.maxDesc)) {
  435.            fprintf(stderr,"%s:PrintFileLayoutSummary: bad file number %d at %d\n", deviceName, fileSumPtr->fileNumber, startAddress);
  436.            goto out;
  437.         }
  438.         status = LfsFileOpen(lfsPtr, fileSumPtr->fileNumber, &filePtr);
  439.         if (status != SUCCESS) {
  440.         dead = TRUE;
  441.         } else {
  442.         dead = FALSE;
  443.         }
  444.  
  445.         printf("Addr %d File %d blocks %d version %d dataBlocks %d %s\n",
  446.         startAddress - fileSumPtr->numBlocks,
  447.         fileSumPtr->fileNumber, fileSumPtr->numBlocks,
  448.         fileSumPtr->truncVersion,
  449.         fileSumPtr->numDataBlocks,
  450.         dead ? "dead" : "alive");
  451.  
  452.         /*
  453.          * For each block ... 
  454.          */
  455.         blockArray = (int *)(summaryPtr + sizeof(LfsFileLayoutSummary));
  456.         firstBlock = fileSumPtr->numBlocks -
  457.          (fileSumPtr->numDataBlocks-1) * FS_BLOCK_SIZE/blockSize;
  458.         for (i = 0; i < fileSumPtr->numDataBlocks; i++) {
  459.         int addr, blocks;
  460.  
  461.         addr = startAddress - i*FS_BLOCK_SIZE/blockSize - firstBlock;
  462.         blocks = (i == 0) ? firstBlock : (FS_BLOCK_SIZE/blockSize);
  463.         printf("Addr %d File %d block %d %s\n",
  464.             addr, fileSumPtr->fileNumber, blockArray[i],
  465.             (!dead && LfsFileBlockAddr(filePtr,blockArray[i], &sizeJunk) ==  addr) ? "alive" : "dead");
  466.         }
  467.         if (!dead) {
  468.         LfsFileClose(filePtr);
  469.         }
  470.         out:
  471.         startAddress = startAddress - fileSumPtr->numBlocks;
  472.         offset += fileSumPtr->numBlocks;
  473.         summaryPtr += sizeof(LfsFileLayoutSummary) + 
  474.                 fileSumPtr->numDataBlocks * sizeof(int); 
  475.         break;
  476.       }
  477.  
  478.     case LFS_FILE_LAYOUT_DIR_LOG: {
  479.         LfsFileLayoutLog    *logSumPtr;
  480.         int            numBlocks;
  481.         int            i, addr, blocks;
  482.         LfsDirOpLogBlockHdr *hdrPtr = (LfsDirOpLogBlockHdr *) NIL;
  483.  
  484.         /* 
  485.          * Directory log info is not needed during clean so we 
  486.          * just skip over it.
  487.          */
  488.          logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  489.          summaryPtr = summaryPtr + sizeof(LfsFileLayoutLog);
  490.          numBlocks = logSumPtr->numBlocks;
  491.          addr = startAddress;
  492.          for (i = 0; i < logSumPtr->numDataBlocks; i++) {
  493.         if (numBlocks > FS_BLOCK_SIZE/blockSize) {
  494.             blocks = FS_BLOCK_SIZE/blockSize;
  495.         } else {
  496.             blocks = numBlocks;
  497.         }
  498.  
  499.             hdrPtr = (LfsDirOpLogBlockHdr *)
  500.              LfsSegFetchBlock(segPtr, offset, blocks*blockSize);
  501.         addr -= blocks;
  502.         offset += blocks;
  503.         if (hdrPtr->magic != LFS_DIROP_LOG_MAGIC) {
  504.             fprintf(stderr,"Bad dir op log magic number.\n");
  505.         }
  506.         ShowDirLogBlock(hdrPtr, addr);
  507.         LfsSegReleaseBlock(segPtr, (char *) hdrPtr);
  508.         }
  509.  
  510.         startAddress = startAddress - logSumPtr->numBlocks;
  511.         break;
  512.     }
  513.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  514.     case LFS_FILE_LAYOUT_INDIRECT: 
  515.     default: {
  516.         panic("Unknown type");
  517.     }
  518.       }
  519.     }
  520.  
  521. }
  522.  
  523. static void
  524. ShowDirLogBlock(hdrPtr, addr)
  525.     LfsDirOpLogBlockHdr *hdrPtr;
  526.     int addr;
  527. {
  528.     LfsDirOpLogEntry *entryPtr, *limitPtr;
  529.  
  530.     limitPtr = (LfsDirOpLogEntry *) (((char *) hdrPtr) + hdrPtr->size);
  531.     entryPtr = (LfsDirOpLogEntry *) (hdrPtr+1);
  532.     while (entryPtr < limitPtr) {
  533.     entryPtr->dirEntry.fileName[entryPtr->dirEntry.nameLength] = '\0';
  534.     printf("Addr %d LogSeqNum %d %s %d \"%s\" links %d in %d at %d\n",
  535.         addr,
  536.         entryPtr->hdr.logSeqNum, 
  537.         DirOpFlagsToString(entryPtr->hdr.opFlags), 
  538.         entryPtr->dirEntry.fileNumber, 
  539.         entryPtr->dirEntry.fileName,
  540.         entryPtr->hdr.linkCount,
  541.         entryPtr->hdr.dirFileNumber,
  542.         entryPtr->hdr.dirOffset);
  543.     entryPtr = (LfsDirOpLogEntry *) 
  544.              (((char *)entryPtr) + LFS_DIR_OP_LOG_ENTRY_SIZE(entryPtr));
  545.     }
  546.  
  547. }
  548.  
  549. static char *
  550. DirOpFlagsToString(opFlags)
  551.     int opFlags;
  552. {
  553.     int op = opFlags & FSDM_LOG_OP_MASK;
  554.     char buffer[128];
  555.     static char *opcodes[] = {"UNKNOWN", "CREATE", "UNLINK", "LINK", 
  556.             "RENAME_DELETE", "RENAME_LINK", "RENAME_LINK", 
  557.             "UNKNOWN"};
  558.     if ((op < 0) || (op >= sizeof(opcodes)/sizeof(opcodes[0]))) {
  559.     op = sizeof(opcodes)/sizeof(opcodes[0])-1;
  560.     }
  561.     strcpy(buffer,opcodes[op]);
  562.     if (opFlags & FSDM_LOG_STILL_OPEN) {
  563.     strcat(buffer, "-OPEN");
  564.     opFlags ^= FSDM_LOG_STILL_OPEN;
  565.     }
  566.     if (opFlags & FSDM_LOG_START_ENTRY) {
  567.     strcat(buffer, "-START");
  568.     opFlags ^= FSDM_LOG_START_ENTRY;
  569.     }
  570.     if (opFlags & FSDM_LOG_END_ENTRY) {
  571.     strcat(buffer, "-END");
  572.     opFlags ^= FSDM_LOG_END_ENTRY;
  573.     }
  574.     if (opFlags & FSDM_LOG_IS_DIRECTORY) {
  575.     strcat(buffer, "-DIR");
  576.     opFlags ^= FSDM_LOG_IS_DIRECTORY;
  577.     }
  578.     if (opFlags & ~FSDM_LOG_OP_MASK) {
  579.     strcat(buffer, "-UNKNOWN");
  580.     }
  581.     return buffer;
  582.  
  583. }
  584. static char *
  585. FileTypeToString(fileType)
  586.     int fileType;
  587. {
  588.     static char *names[] = { "File", "Dir", "Symlink", "Rmtlink", "Dev", 
  589.                  "Rmtdev", "Pipe", "NamedPipe", "Pdev", "Pfs",
  590.                  "XtraFile", "Unknown"};
  591.  
  592.     if ((fileType < 0) || (fileType >= sizeof(names)/sizeof(names[0]))) {
  593.     fileType = sizeof(names)/sizeof(names[0])-1;
  594.     }
  595.     return names[fileType];
  596. }
  597.  
  598.  
  599. @
  600.